package net.sk.china.front.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import net.sk.china.common.constants.Constants;
import net.sk.china.common.exception.TalkException;
import net.sk.china.common.model.order.StoreOrder;
import net.sk.china.common.model.user.User;
import net.sk.china.common.response.NotifyResponse;
import net.sk.china.common.utils.DateUtil;
import net.sk.china.common.utils.RedisUtil;
import net.sk.china.common.utils.TalkUtil;
import net.sk.china.common.utils.WxPayUtil;
import net.sk.china.common.vo.AttachVo;
import net.sk.china.front.service.NotifyService;
import net.sk.china.front.service.order.StoreOrderService;
import net.sk.china.front.service.user.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.HashMap;

/**
 * NotifyServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * // | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * // +----------------------------------------------------------------------
 * // | Copyright (c) 2018-2024 聊来 All rights reserved.
 * // +----------------------------------------------------------------------
 * // | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * // +----------------------------------------------------------------------
 * // | @Author: 聊来 <18970881148@qq.com>
 * // +----------------------------------------------------------------------
 * // | DateTime: 2024/6/5 11:04
 * // +----------------------------------------------------------------------
 */

@Service
public class NotifyServiceImpl implements NotifyService {
    private final static Logger logger = LoggerFactory.getLogger(NotifyServiceImpl.class);

    private final UserService userService;

    private final StoreOrderService storeOrderService;

    private final TransactionTemplate transactionTemplate;

    private final RedisUtil redisUtil;

    public NotifyServiceImpl(UserService userService, StoreOrderService storeOrderService, TransactionTemplate transactionTemplate, RedisUtil redisUtil) {
        this.userService = userService;
        this.storeOrderService = storeOrderService;
        this.transactionTemplate = transactionTemplate;
        this.redisUtil = redisUtil;
    }

    @Override
    public String weChat(String xmlInfo) {
        logger.info("微信支付异步通知：" + xmlInfo);
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        if(StrUtil.isBlank(xmlInfo)){
            sb.append("<return_code><![CDATA[FAIL]]></return_code>");
            sb.append("<return_msg><![CDATA[xmlInfo is blank]]></return_msg>");
            sb.append("</xml>");
            logger.error("wechat callback error : " + sb.toString());
            return sb.toString();
        }

        try{
            HashMap<String, Object> map = WxPayUtil.processResponseXml(xmlInfo);
            // 通信是否成功
            String returnCode = (String) map.get("return_code");
            if (!returnCode.equals(Constants.SUCCESS)) {
                sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
                sb.append("<return_msg><![CDATA[OK]]></return_msg>");
                sb.append("</xml>");
                logger.error("wechat callback error : wx pay return code is fail returnMsg : " + map.get("return_msg"));
                return sb.toString();
            }
            // 交易是否成功
            String resultCode = (String) map.get("result_code");
            if (!resultCode.equals(Constants.SUCCESS)) {
                sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
                sb.append("<return_msg><![CDATA[OK]]></return_msg>");
                sb.append("</xml>");
                logger.error("wechat callback error : wx pay result code is fail");
                return sb.toString();
            }

            // 解析xml
            NotifyResponse response = TalkUtil.mapToObj(map, NotifyResponse.class);
            logger.info("微信支付异步通知数据：" + response);
            AttachVo attachVo = JSONObject.toJavaObject(JSONObject.parseObject(response.getAttach()), AttachVo.class);

            // 根据业务类型写对应逻辑代码
            User user = userService.getById(attachVo.getUserId());
            if (ObjectUtil.isNull(user)) {
                throw new TalkException("用户信息错误！");
            }

            // 订单
            if (Constants.SERVICE_PAY_TYPE_ORDER.equals(attachVo.getType())) {
                StoreOrder orderParam = new StoreOrder();
                orderParam.setOutTradeNo(response.getOutTradeNo());
                orderParam.setUid(attachVo.getUserId());

                StoreOrder storeOrder = storeOrderService.getOrderIdAndUidToInfo(response.getOutTradeNo(), attachVo.getUserId());
                if (ObjectUtil.isNull(storeOrder)) {
                    logger.error("wechat pay error : 订单信息不存在==》" + response.getOutTradeNo());
                    throw new TalkException("wechat pay error : 订单信息不存在==》" + response.getOutTradeNo());
                }
                if (storeOrder.getPaid()) {
                    logger.error("wechat pay error : 订单已处理==》" + response.getOutTradeNo());
                    sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
                    sb.append("<return_msg><![CDATA[OK]]></return_msg>");
                    sb.append("</xml>");
                    return sb.toString();
                }

                // 添加支付成功redis队列
                Boolean execute = transactionTemplate.execute(e -> {
                    storeOrder.setPaid(true);
                    storeOrder.setPayTime(DateUtil.getNowTime());
                    storeOrderService.updateById(storeOrder);

                    return Boolean.TRUE;
                });
                if (Boolean.FALSE.equals(execute)) {
                    logger.error("wechat pay error : 订单更新失败==》" + response.getOutTradeNo());
                    throw new TalkException("wechat pay error : 订单更新失败==》" + response.getOutTradeNo());
                }
                redisUtil.lPush(net.sk.china.front.constants.Constants.ORDER_TASK_PAY_SUCCESS_AFTER, storeOrder.getOrderId());
            }

            sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
            sb.append("<return_msg><![CDATA[OK]]></return_msg>");
        } catch (Exception e){
            sb.append("<return_code><![CDATA[FAIL]]></return_code>");
            sb.append("<return_msg><![CDATA[").append(e.getMessage()).append("]]></return_msg>");
            logger.error("wechat pay error : 业务异常==》" + e.getMessage());
        }
        sb.append("</xml>");
        logger.error("wechat callback response : " + sb);
        return sb.toString();
    }
}
